import {
  generateFieldNodePortsByFieldName,
  generateTableNodePorts,
  nodePortsGroups,
} from './node-port'
import {
  NODE_HEADER_HEIGHT,
  NODE_LINE_HEIGHT,
  NODE_WIDTH,
  EDGE_DEFAULT_COLOR,
  EDGE_LINK_HIGHLIGHT_COLOR,
  EDGE_WARNING_HIGHLIGHT_COLOR,
  GRAPH_SCALING_MIN,
  GRAPH_SCALING_MAX,
} from './constants'
import { flatten } from 'lodash'

/**
 * X6 graph 配置项
 */
export const graphConfigOptions: any = {
  autoSize: true,
  // 所有缩放限制
  scaling: {
    min: GRAPH_SCALING_MIN,
    max: GRAPH_SCALING_MAX,
  },
  autoResize: true,
  // 拖拽
  panning: {
    enabled: true,
    // modifiers: 'shift',
  },
  mousewheel: {
    enabled: true,
    zoomAtMousePosition: true,
    minScale: GRAPH_SCALING_MIN,
    maxScale: GRAPH_SCALING_MAX,
  },
  grid: {
    size: 10, // 网格大小 10px
    type: 'dot', // 指定网格类型
    visible: false, // 绘制网格，默认绘制 dot 类型网格
  },
  // 设置画布背景颜色
  background: {
    color: '#fff',
  },
  // 连线选项
  connecting: {
    router: {
      name: 'er',
      args: {
        direction: 'L',
      },
    },
    connector: {
      name: 'rounded',
    },
  },
  // 限制拖动节点
  interacting: {
    nodeMovable: false,
  },
}

/**
 * generate X6 节点模板
 * @param nodes 后端节点数据
 * @param nodeType FIELD-字段级血缘节点 TABLE-表格级血缘节点
 */
export function generateNodesTemplate(nodes: any, nodeType: string) {
  if (nodes && nodes.length === 0) {
    return []
  }
  return nodes?.map((node: any) => {
    let ports: any[] = []
    if (nodeType === 'FIELD') {
      ports = flatten(
        node.tableFieldDetailList.map((field: any, index: number) =>
          generateFieldNodePortsByFieldName(field, index)
        )
      )
    } else if (nodeType === 'TABLE') {
      const { haveEntrance, haveExit } = node
      ports = generateTableNodePorts(haveEntrance, haveExit)
    }
    const height: number =
      nodeType === 'FIELD'
        ? node.tableFieldDetailList.length * NODE_LINE_HEIGHT +
          NODE_HEADER_HEIGHT +
          NODE_LINE_HEIGHT
        : NODE_HEADER_HEIGHT + NODE_LINE_HEIGHT // 表格级 & 字段级 tableName 另起一行显示
    const nodeSize: any = { width: NODE_WIDTH, height }
    const { databaseName, tableName } = node
    const nodeId: string = `${databaseName}_${tableName}`
    return {
      id: nodeId,
      x: node.x,
      y: node.y,
      width: NODE_WIDTH,
      height,
      size: nodeSize, // 提供给布局算法 number | [width, height] | {width, height} | [40, 40]
      shape:
        nodeType === 'FIELD'
          ? 'field-data-lineage-node'
          : 'table-data-lineage-node',
      data: {
        id: nodeId,
        tableType: node.tableType || 'DEFAULT',
        ...node,
      },
      zIndex: 2,
      // 非标属性, 用户交互
      states: {
        selected: false, // 选中
        onHoverHighlightLink: false, // 在高亮链路上(hover)
        onSelectedHighlightLink: false, // 在选择高亮链路上
        onHoverHighlightLinkField: [], // hover高亮链路上的字段
        onSelectedHighlightLinkField: [], // selected高亮链路上的字段
        haveHighlightLink: false, // 有高亮链路
      },
      ports: {
        groups: nodePortsGroups,
        items: ports,
      },
    }
  })
}

/**
 * 根据颜色和类型生成边
 * @param lineInfo
 */
export function generateEdgesAttributes(lineInfo: {
  lineColor: string
  lineType: string
}) {
  const { lineColor = 'BLACK', lineType = 'SOLID' } = lineInfo
  const lineColorMap: any = {
    RED: EDGE_WARNING_HIGHLIGHT_COLOR,
    BLACK: EDGE_DEFAULT_COLOR,
  }
  const edgeBaseColor: string = lineColorMap[lineColor]
  const strokeDasharray: string = lineType === 'DASH' ? '5, 5' : '5, 0'
  return {
    edgeBaseColor,
    strokeDasharray,
  }
}

/**
 * 生成 X6 边模板
 * @param edges 后端边数据
 * @param nodeType FIELD-字段级血缘节点 TABLE-表格级血缘节点
 */
export function generateEdgesTemplate(edges: any, nodeType: string) {
  if (edges && edges.length === 0) {
    return []
  }
  return edges?.map((edge: any) => {
    const { lineColor, lineType } = edge
    const { edgeBaseColor, strokeDasharray } = generateEdgesAttributes({
      lineColor,
      lineType,
    })
    const edgeId: string =
      nodeType === 'FIELD'
        ? `${edge.source.databaseName}_${edge.source.tableName}_${edge.source.fieldName}_${edge.target.databaseName}_${edge.target.tableName}_${edge.target.fieldName}`
        : `${edge.source.databaseName}_${edge.source.tableName}_${edge.target.databaseName}_${edge.target.tableName}`
    return {
      id: edgeId,
      data: {
        id: edgeId,
        ...edge,
      },
      zIndex: 1,
      // 非标属性, 用户交互
      states: {
        baseColor: edgeBaseColor, // 基础色
        hoverHighlightColor: EDGE_LINK_HIGHLIGHT_COLOR, // hover 高亮色
        hoverLinkHighlightColor: EDGE_LINK_HIGHLIGHT_COLOR, // hover 链路高亮色
        selectedLinkHighlightColor: EDGE_LINK_HIGHLIGHT_COLOR, // selected 链路高亮色
        selectedHighlightColor: EDGE_LINK_HIGHLIGHT_COLOR, // selected 高亮色
        selected: false, // 选中
        hover: false,
        onHoverHighlightLink: false, // 在 hover 高亮链路上
        onSelectedHighlightLink: false, // 在 selected 高亮链路上
      },
      source: {
        cell: `${edge.source.databaseName}_${edge.source.tableName}`,
        port:
          nodeType === 'FIELD' ? `out-${edge.source.fieldName}` : 'out-port',
      },
      target: {
        cell: `${edge.target.databaseName}_${edge.target.tableName}`,
        port: nodeType === 'FIELD' ? `in-${edge.target.fieldName}` : 'in-port',
      },
      // 实例化 graph 时 connecting 中配置 router-路由 connector-连接器
      attrs: {
        line: {
          stroke: edgeBaseColor,
          strokeWidth: 1,
          targetMarker: {
            name: 'classic',
            size: 6,
          },
          zIndex: 1,
          strokeDasharray,
        },
        wrap: {
          strokeWidth: 10,
          strokeLinecap: 'butt',
        },
      },
      label:
        lineColor === 'RED' && lineType === 'SOLID'
          ? {
              markup: [
                {
                  tagName: 'circle',
                  selector: 'labelBody',
                },
                {
                  tagName: 'text',
                  selector: 'labelText',
                },
              ],
              attrs: {
                labelText: {
                  text: '!',
                  fill: '#fff',
                  textAnchor: 'middle',
                  fontSize: 12,
                  textVerticalAnchor: 'middle',
                  cursor: 'pointer',
                },
                labelBody: {
                  ref: 'labelText',
                  cursor: 'pointer',
                  r: 7,
                  stroke: '#E6505A',
                  fill: '#E6505A',
                  strokeWidth: 1,
                  event: 'edge:detail',
                },
              },
            }
          : null,
    }
  })
}
